package com.zbiti.anvil.basic.admin.gateway.common.config;

import com.zbiti.framework.security.core.delegate.AnvilUserDetailsDelegate;
import com.zbiti.framework.security.core.helper.AnvilTokenHelper;
import com.zbiti.framework.security.core.utils.SecurityUtils;
import com.zbiti.module.system.base.api.domain.SysRoleDomain;
import com.zbiti.module.system.base.api.domain.SysUserDomain;
import com.zbiti.sdk.common.config.ISessionProxy;
import com.zbiti.sdk.common.exception.BusinessException;
import com.zbiti.sdk.common.hold.SessionProxyHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Session代理注入配置
 *
 * @author Fanyc
 * @date 2020-09-30 17:16
 */
@Configuration
public class SecuritySessionProxyConfig {

    @Autowired
    private AnvilTokenHelper anvilTokenHelper;

    /**
     * Security的Session代理对象
     *
     * @return 代理对象
     */
    @Bean("securitySessionProxy")
    @ConditionalOnMissingBean(name = "securitySessionProxy")
    public SecuritySessionProxy securitySessionProxy() {
        SecuritySessionProxy sessionProxy = new SecuritySessionProxy(anvilTokenHelper);
        SessionProxyHolder.setSessionProxy(sessionProxy);
        return sessionProxy;
    }

    @SuppressWarnings("unchecked")
    public static class SecuritySessionProxy implements ISessionProxy {

        /**
         * token帮助类
         */
        private AnvilTokenHelper anvilTokenHelper;

        /**
         * 构造函数
         *
         * @param anvilTokenHelper token帮助类
         */
        public SecuritySessionProxy(AnvilTokenHelper anvilTokenHelper) {
            this.anvilTokenHelper = anvilTokenHelper;
        }

        /**
         * 获取Session的ID
         *
         * @return SessionId
         */
        @Override
        public String getSessionId() {
            AnvilUserDetailsDelegate principal = getPrincipal(AnvilUserDetailsDelegate.class);
            return principal != null ? principal.getToken() : null;
        }

        /**
         * 获取用户ID
         *
         * @return 用户ID
         */
        @Override
        public Serializable getUserId() {
            SysUserDomain userInfo = getUserInfo(SysUserDomain.class);
            return userInfo != null ? userInfo.getUserId() : null;
        }

        /**
         * 获取用户登录名
         *
         * @return 登录名
         */
        @Override
        public String getLoginName() {
            SysUserDomain userInfo = getUserInfo(SysUserDomain.class);
            return userInfo != null ? userInfo.getLoginName() : null;
        }

        /**
         * 获取用户名
         *
         * @return 用户名
         */
        @Override
        public String getUserName() {
            SysUserDomain userInfo = getUserInfo(SysUserDomain.class);
            return userInfo != null ? userInfo.getUserName() : null;
        }

        /**
         * 获取部门ID
         *
         * @return 返回部门ID
         */
        @Override
        public String getDeptId() {
            SysUserDomain userInfo = getUserInfo(SysUserDomain.class);
            return (userInfo != null && userInfo.getDeptId() != null) ? userInfo.getDeptId().toString() : null;
        }

        /**
         * 获取部门编码
         *
         * @return 返回部门编码
         */
        @Override
        public String getDeptCode() {
            SysUserDomain userInfo = getUserInfo(SysUserDomain.class);
            return userInfo != null ? userInfo.getDeptCode() : null;
        }

        /**
         * 获取部门名称
         *
         * @return 返回部门名称
         */
        @Override
        public String getDeptName() {
            SysUserDomain userInfo = getUserInfo(SysUserDomain.class);
            return userInfo != null ? userInfo.getDeptName() : null;
        }

        /**
         * 获取部门ID祖辈路径
         *
         * @return 部门ID祖辈路径
         */
        @Override
        public String getDeptIdAncestors() {
            SysUserDomain userInfo = getUserInfo(SysUserDomain.class);
            return (userInfo != null && userInfo.getDept() != null) ? userInfo.getDept().getAncestors() : null;
        }

        /**
         * 获取公司ID
         *
         * @return 返回公司ID
         */
        @Override
        public String getCompanyId() {
            SysUserDomain userInfo = getUserInfo(SysUserDomain.class);
            return (userInfo != null && userInfo.getCompanyId() != null) ? userInfo.getCompanyId().toString() : null;
        }

        /**
         * 获取公司编码
         *
         * @return 返回公司编码
         */
        @Override
        public String getCompanyCode() {
            SysUserDomain userInfo = getUserInfo(SysUserDomain.class);
            return userInfo != null ? userInfo.getCompanyCode() : null;
        }

        /**
         * 获取公司名称
         *
         * @return 返回公司名称
         */
        @Override
        public String getCompanyName() {
            SysUserDomain userInfo = getUserInfo(SysUserDomain.class);
            return userInfo != null ? userInfo.getCompanyName() : null;
        }

        /**
         * 获取部门ID祖辈路径
         *
         * @return 部门ID祖辈路径
         */
        @Override
        public String getCompanyIdAncestors() {
            SysUserDomain userInfo = getUserInfo(SysUserDomain.class);
            return (userInfo != null && userInfo.getCompany() != null) ? userInfo.getCompany().getAncestors() : null;
        }

        /**
         * 获取当前登录的用户Bean.
         *
         * @param clazz 类类型
         * @return 当前登录的用户Bean
         */
        @Override
        public <T> T getUserInfo(Class<T> clazz) {
            try {
                AnvilUserDetailsDelegate principal = getPrincipal(AnvilUserDetailsDelegate.class);
                return principal != null ? (T) principal.getDomain() : null;
            } catch (Exception e) {
                throw new BusinessException("获取用户登录信息异常");
            }
        }

        /**
         * 判断是否为管理员用户
         *
         * @return 是否为管理员用户
         */
        @Override
        public boolean isAdmin() {
            SysUserDomain userInfo = getUserInfo(SysUserDomain.class);
            return userInfo.isAdmin();
        }

        /**
         * 获取当前登录用户的角色Bean列表.
         *
         * @param clazz 类类型
         * @return 当前登录用户的角色列表
         */
        @Override
        public <T> List<T> getRolesInfo(Class<T> clazz) {
            AnvilUserDetailsDelegate principal = getPrincipal(AnvilUserDetailsDelegate.class);
            return (List<T>) principal.getRoles();
        }

        /**
         * 获取当前用户角色ID列表
         *
         * @return 当前用户角色ID列表
         */
        @Override
        public List<Serializable> getRoleIds() {
            List<SysRoleDomain> rolesInfo = getRolesInfo(SysRoleDomain.class);
            return rolesInfo.stream().map(SysRoleDomain::getRoleId).collect(Collectors.toList());
        }

        /**
         * 获取当前用户超级管理角色列表
         *
         * @param clazz 类类型
         * @return 当前用户超级管理角色列表
         */
        @Override
        public <T> List<T> getSuperRoles(Class<T> clazz) {
            AnvilUserDetailsDelegate principal = getPrincipal(AnvilUserDetailsDelegate.class);
            return (List<T>) principal.getRoles().stream().filter(e -> e.getRoleTypeEnum().isPresent() && e.isSuperRole()).collect(Collectors.toList());
        }

        /**
         * 获取当前用户超级管理角色ID列表
         *
         * @return 当前用户超级管理角色ID列表
         */
        @Override
        public List<Serializable> getSuperRoleIds() {
            List<SysRoleDomain> rolesInfo = getSuperRoles(SysRoleDomain.class);
            return rolesInfo.stream().map(SysRoleDomain::getRoleId).collect(Collectors.toList());
        }

        /**
         * 获取当前用户配置管理角色列表
         *
         * @param clazz 类类型
         * @return 当前用户配置管理角色列表
         */
        @Override
        public <T> List<T> getConfigRoles(Class<T> clazz) {
            AnvilUserDetailsDelegate principal = getPrincipal(AnvilUserDetailsDelegate.class);
            return (List<T>) principal.getRoles().stream().filter(e -> e.getRoleTypeEnum().isPresent() && e.isConfigRole()).collect(Collectors.toList());
        }

        /**
         * 获取当前用户配置管理角色ID列表
         *
         * @return 获取当前用户配置管理角色ID列表
         */
        @Override
        public List<Serializable> getConfigRoleIds() {
            List<SysRoleDomain> rolesInfo = getConfigRoles(SysRoleDomain.class);
            return rolesInfo.stream().map(SysRoleDomain::getRoleId).collect(Collectors.toList());
        }

        /**
         * 获取当前用户业务应用角色列表
         *
         * @param clazz 类类型
         * @return 当前用户业务应用角色色列表
         */
        @Override
        public <T> List<T> getApplicationRoles(Class<T> clazz) {
            AnvilUserDetailsDelegate principal = getPrincipal(AnvilUserDetailsDelegate.class);
            return (List<T>) principal.getRoles().stream().filter(e -> e.getRoleTypeEnum().isPresent() && e.isApplicationRole()).collect(Collectors.toList());
        }

        /**
         * 获取当前用户业务应用角色ID列表
         *
         * @return 获取当前用户业务应用角色ID列表
         */
        @Override
        public List<Serializable> getApplicationRoleIds() {
            List<SysRoleDomain> rolesInfo = getApplicationRoles(SysRoleDomain.class);
            return rolesInfo.stream().map(SysRoleDomain::getRoleId).collect(Collectors.toList());
        }

        @Override
        public <T> List<T> getCustom1Roles(Class<T> aClass) {
            AnvilUserDetailsDelegate principal = getPrincipal(AnvilUserDetailsDelegate.class);
            return (List<T>) principal.getRoles().stream().filter(e -> e.getRoleTypeEnum().isPresent() && e.isCustom1Role()).collect(Collectors.toList());
        }

        /**
         * 获取当前用户自定义1角色ID列表
         *
         * @return 获取当前用户自定义1角色ID列表
         */
        @Override
        public List<Serializable> getCustom1RoleIds() {
            List<SysRoleDomain> rolesInfo = getCustom1Roles(SysRoleDomain.class);
            return rolesInfo.stream().map(SysRoleDomain::getRoleId).collect(Collectors.toList());
        }

        @Override
        public <T> List<T> getCustom2Roles(Class<T> aClass) {
            AnvilUserDetailsDelegate principal = getPrincipal(AnvilUserDetailsDelegate.class);
            return (List<T>) principal.getRoles().stream().filter(e -> e.getRoleTypeEnum().isPresent() && e.isCustom2Role()).collect(Collectors.toList());
        }

        /**
         * 获取当前用户自定义2角色ID列表
         *
         * @return 获取当前用户自定义2角色ID列表
         */
        @Override
        public List<Serializable> getCustom2RoleIds() {
            List<SysRoleDomain> rolesInfo = getCustom2Roles(SysRoleDomain.class);
            return rolesInfo.stream().map(SysRoleDomain::getRoleId).collect(Collectors.toList());
        }

        @Override
        public <T> List<T> getCustom3Roles(Class<T> aClass) {
            AnvilUserDetailsDelegate principal = getPrincipal(AnvilUserDetailsDelegate.class);
            return (List<T>) principal.getRoles().stream().filter(e -> e.getRoleTypeEnum().isPresent() && e.isCustom3Role()).collect(Collectors.toList());
        }

        /**
         * 获取当前用户自定义3角色ID列表
         *
         * @return 获取当前用户自定义3角色ID列表
         */
        @Override
        public List<Serializable> getCustom3RoleIds() {
            List<SysRoleDomain> rolesInfo = getCustom3Roles(SysRoleDomain.class);
            return rolesInfo.stream().map(SysRoleDomain::getRoleId).collect(Collectors.toList());
        }

        /**
         * 获取Session中的值
         *
         * @param key 键
         * @return 对应的值
         */
        @Override
        public <T> T getSessionAtt(String key) {
            try {
                AnvilUserDetailsDelegate principal = getPrincipal(AnvilUserDetailsDelegate.class);
                return principal != null ? (T) principal.getParam(key) : null;
            } catch (Exception e) {
                throw new BusinessException("保存数据到Session异常");
            }
        }

        /**
         * 设置值到Session中
         *
         * @param key   键
         * @param value 值
         */
        @Override
        public void setSessionAtt(String key, Object value) {
            try {
                AnvilUserDetailsDelegate principal = getPrincipal(AnvilUserDetailsDelegate.class);
                principal.putParam(key, value);
                this.anvilTokenHelper.saveToken(principal);
            } catch (Exception e) {
                throw new BusinessException("保存数据到Session异常");
            }
        }

        /**
         * 获取登录令牌
         *
         * @param clazz 令牌类型
         * @return 登录令牌
         */
        @Override
        public <T> T getPrincipal(Class<T> clazz) {
            Object principal = SecurityUtils.getPrincipal();
            return (principal != null && principal.getClass().equals(AnvilUserDetailsDelegate.class)) ? (T) principal : null;
        }

    }
}
